package com.bupt.service.common.impl;

import com.bupt.Factory.ProjectFactory;
import com.bupt.Factory.ProjectResultCenter;

import com.bupt.algorithm.TrafficSystemLimitRouteFinder;
import com.bupt.basic.DemandReportService;
import com.bupt.basic.IBasicNetWork;
import com.bupt.basic.Project;
import com.bupt.dto.network.Node;
import com.bupt.entity.*;
import com.bupt.exception.BaseException;
import com.bupt.service.common.StrategyService;
import com.bupt.service.system.SysLoginService;
import com.bupt.utils.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.Array;
import java.util.*;

@Service("strategyService")
public class StrategyServiceImpl implements StrategyService {
    private static final Object lock = new Object();


    //记录链路上存在的业务信息
    Map<String, ProjectResultCenter.LinkMsg> linkMsg = new HashMap<>();
    //记录每一次规划后各业务的状态
    Map<String, String> planStatus = new HashMap<>();
    //记录每一次规划各业务的原因
    Map<String, String> planReason = new HashMap<>();

    @Resource
    private SysLoginService sysLoginService;


    @Override
    public Object plan(HttpServletRequest request, String projectId, String strategy, String layer,
                       Integer resLimit, Integer hopLimit, String[] selectedTraffic) throws BaseException {
        synchronized (lock){
            LocalVerify.verifyString(projectId,"项目Id");
            //目前reslimit和selectedTraffic没有用到
            //保存返回值

            //规划层限制
            boolean isLayerLimit=false;
            if(layer!=null) isLayerLimit=layer.equals(LayerString.WDM)||layer.equals(LayerString.OTN)||layer.equals(LayerString.SDH);

            //跳数显示
            boolean isHopLimit=false;
            if(hopLimit!=null) isHopLimit=hopLimit>0;

            int count=0;//规划成功的业务个数
            int portUp=0;//四种端口类型
            int portDown=0;
            int portSpare=0;
            int portLink=0;

            Project project = ProjectFactory.getObjectFromFile(projectId, ProjectFactory.storePath);

            if(project==null) throw new BaseException("此项目不存在");

            if(project.getBasicNetWork().getNodeList().size()==0)throw new BaseException("此项目无节点");
            if(project.getBasicNetWork().getFiberLinks().size()==0)throw new BaseException("此项目无光纤链路");
            if(project.getDemandList().size()==0)throw new BaseException("此项目中无业务");

            //规划前先进行对上一次的规划资源进行清理和释放
            clear(project);
            Map<String,List<IBasicNetWork.PortL>> ports=project.getBasicNetWork().getPorts();
           //设置算法
            TrafficSystemLimitRouteFinder algorithm = new TrafficSystemLimitRouteFinder();
            algorithm.setStrategy(strategy);

            //先搭建好项目的result的结构
            HashMap<String, ProjectResultCenter.RouteType> workRouteMsg = new HashMap<>();
            HashMap<String, ProjectResultCenter.RouteType> protectRouteMsg = new HashMap<>();

            linkMsg.clear();
            planStatus.clear();
            planReason.clear();

            for (DemandReportService traffic : project.getDemandList()) {
                if(isLayerLimit&&layer!=null&&!traffic.getLayer().equals(layer)){
                    planStatus.put(traffic.getId(),"error");
                    planReason.put(traffic.getId(),"规划失败，业务不在相应的规划层级");
                    continue;
                }

                List<IBasicNetWork.BasicNode> nodes = new ArrayList<>(project.getBasicNetWork().getNodeList());
                List<IBasicNetWork.BasicLink> links = new ArrayList<>();
                IBasicNetWork.BasicNode fromNode = project.searchNodeById(traffic.getNodeHead());
                IBasicNetWork.BasicNode toNode = project.searchNodeById(traffic.getNodeTail());

                //业务承载路由
                String carriedLayer = traffic.getLayer();

                List<IBasicNetWork.BasicLink> balanceUsedLinks1 = new ArrayList<>();//负载均衡中已承载过一个同源同溯业务的链路组
                List<IBasicNetWork.BasicLink> balanceUsedLinks2 = new ArrayList<>();//负载均衡中已承载过两个同源同溯业务的链路组

                if(carriedLayer.equals(LayerString.WDM)){
                    if(project.getBasicNetWork().getWdmLinks()==null||project.getBasicNetWork().getWdmLinks().size()==0){
                        traffic.setStatus(TrafficStatus.Fault);
                        traffic.setReason("无WDM层链路，规划失败");
                        planStatus.put(traffic.getId(),"error");
                        planReason.put(traffic.getId(),"规划失败，无WDM层链路");
                        continue;
                    }
                    for (IBasicNetWork.BasicLink wdmLink : project.getBasicNetWork().getWdmLinks()) {
                        if (strategy.equals("balance")) {
                            if (judgeTYTS(linkMsg, wdmLink.getId(), project.getDemandList(), traffic.getNodeHeadName(), traffic.getNodeTailName()) == 1) {
                                if (wdmLink instanceof IBasicNetWork.HaveTraffic) {
                                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) wdmLink;
                                    if (h.canAdd(traffic.getBandwidthNum())) {
                                        balanceUsedLinks1.add(wdmLink);
                                    }
                                }
                                continue;
                            } else if (judgeTYTS(linkMsg, wdmLink.getId(), project.getDemandList(), traffic.getNodeHeadName(), traffic.getNodeTailName()) > 1) {
                                if (wdmLink instanceof IBasicNetWork.HaveTraffic) {
                                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) wdmLink;
                                    if (h.canAdd(traffic.getBandwidthNum())) {
                                        balanceUsedLinks2.add(wdmLink);
                                    }
                                }
                                continue;
                            }
                        }

                        if(wdmLink instanceof IBasicNetWork.HaveTraffic){
                            IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) wdmLink;

                            //如果子粒度可以承载，就在links中添加wdmLink
                            if(h.canAdd(traffic.getBandwidthNum())){
                              links.add(wdmLink);
                            }
                        }
                    }
                }else if(carriedLayer.equals(LayerString.OTN)){
                    if(project.getBasicNetWork().getOtnLinks()==null||project.getBasicNetWork().getOtnLinks().size()==0){
                        traffic.setStatus(TrafficStatus.Fault);
                        traffic.setReason("无OTN链路，规划失败");
                        planStatus.put(traffic.getId(),"error");
                        planReason.put(traffic.getId(),"规划失败,无OTN链路");
                        continue;
                    }
                    for (IBasicNetWork.BasicLink otnLink : project.getBasicNetWork().getOtnLinks()) {

                        if (strategy.equals("balance")) {
                            if (judgeTYTS(linkMsg, otnLink.getId(), project.getDemandList(), traffic.getNodeHeadName(), traffic.getNodeTailName()) == 1) {
                                if (otnLink instanceof IBasicNetWork.HaveTraffic) {
                                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) otnLink;
                                    //查询是否有可用端口
                                    boolean flagHead=false;
                                    for (IBasicNetWork.PortL port:ports.get(otnLink.getNodeHead())) {
                                        if(port.getLink().getId().equals(otnLink.getId())&&port.getStatus().equals("free")){
                                            flagHead=true;
                                            break;
                                        }
                                    }
                                    boolean flagTail=false;
                                    for (IBasicNetWork.PortL port:ports.get(otnLink.getNodeTail())) {
                                        if(port.getLink().getId().equals(otnLink.getId())&&port.getStatus().equals("free")){
                                            flagTail=true;
                                            break;
                                        }
                                    }
                                    if (h.canAdd(traffic.getBandwidthNum())&&flagHead&&flagTail) {
                                        balanceUsedLinks1.add(otnLink);
                                    }
                                }
                                continue;
                            } else if (judgeTYTS(linkMsg, otnLink.getId(), project.getDemandList(), traffic.getNodeHeadName(), traffic.getNodeTailName()) > 1) {
                                if (otnLink instanceof IBasicNetWork.HaveTraffic) {
                                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) otnLink;
                                    if (h.canAdd(traffic.getBandwidthNum())) {
                                        balanceUsedLinks2.add(otnLink);
                                    }
                                }
                                continue;
                            }
                        }

                        if(otnLink instanceof IBasicNetWork.HaveTraffic){
                            IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) otnLink;
                            //查询是否有可用端口
                            boolean flagHead=false;
                            for (IBasicNetWork.PortL port:ports.get(otnLink.getNodeHead())) {
                                if(port.getLink().getId().equals(otnLink.getId())&&port.getStatus().equals("free")){
                                    flagHead=true;
                                    break;
                                }
                            }
                            boolean flagTail=false;
                            for (IBasicNetWork.PortL port:ports.get(otnLink.getNodeTail())) {
                                if(port.getLink().getId().equals(otnLink.getId())&&port.getStatus().equals("free")){
                                    flagTail=true;
                                    break;
                                }
                            }
                            if(h.canAdd(traffic.getBandwidthNum())&&flagHead&&flagTail){
                                links.add(otnLink);
                            }
                        }
                    }
                }else if(carriedLayer.equals(LayerString.SDH)){
                    if(project.getBasicNetWork().getSdhLinks()==null||project.getBasicNetWork().getSdhLinks().size()==0){
                        traffic.setStatus(TrafficStatus.Fault);
                        traffic.setReason("无SDH链路，规划失败");
                        planStatus.put(traffic.getId(),"error");
                        planReason.put(traffic.getId(),"规划失败，无SDH链路");
                        continue;
                    }
                    for (IBasicNetWork.BasicLink sdhLink : project.getBasicNetWork().getSdhLinks()) {

                        if (strategy.equals("balance")) {
                            if (judgeTYTS(linkMsg, sdhLink.getId(), project.getDemandList(), traffic.getNodeHeadName(), traffic.getNodeTailName()) == 1) {
                                if (sdhLink instanceof IBasicNetWork.HaveTraffic) {
                                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) sdhLink;
                                    //查询是否有可用端口
                                    boolean flagHead=false;
                                    for (IBasicNetWork.PortL port:ports.get(sdhLink.getNodeHead())) {
                                        if(port.getLink().getId().equals(sdhLink.getId())&&port.getStatus().equals("free")){
                                            flagHead=true;
                                            break;
                                        }
                                    }
                                    boolean flagTail=false;
                                    for (IBasicNetWork.PortL port:ports.get(sdhLink.getNodeTail())) {
                                        if(port.getLink().getId().equals(sdhLink.getId())&&port.getStatus().equals("free")){
                                            flagTail=true;
                                            break;
                                        }
                                    }
                                    if (h.canAdd(traffic.getBandwidthNum())&&flagHead&&flagTail) {
                                        balanceUsedLinks1.add(sdhLink);
                                    }
                                }
                                continue;
                            } else if (judgeTYTS(linkMsg, sdhLink.getId(), project.getDemandList(), traffic.getNodeHeadName(), traffic.getNodeTailName()) > 1) {
                                if (sdhLink instanceof IBasicNetWork.HaveTraffic) {
                                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) sdhLink;
                                    //查询是否有可用端口
                                    boolean flagHead=false;
                                    for (IBasicNetWork.PortL port:ports.get(sdhLink.getNodeHead())) {
                                        if(port.getLink().getId().equals(sdhLink.getId())&&port.getStatus().equals("free")){
                                            flagHead=true;
                                            break;
                                        }
                                    }
                                    boolean flagTail=false;
                                    for (IBasicNetWork.PortL port:ports.get(sdhLink.getNodeTail())) {
                                        if(port.getLink().getId().equals(sdhLink.getId())&&port.getStatus().equals("free")){
                                            flagTail=true;
                                            break;
                                        }
                                    }
                                    if (h.canAdd(traffic.getBandwidthNum())&&flagHead&&flagTail) {
                                        balanceUsedLinks2.add(sdhLink);
                                    }
                                }
                                continue;
                            }
                        }

                        if(sdhLink instanceof IBasicNetWork.HaveTraffic){
                            IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) sdhLink;
                            //查询是否有可用端口
                            boolean flagHead=false;
                            for (IBasicNetWork.PortL port:ports.get(sdhLink.getNodeHead())) {
                                if(port.getLink().getId().equals(sdhLink.getId())&&port.getStatus().equals("free")){
                                    flagHead=true;
                                    break;
                                }
                            }
                            boolean flagTail=false;
                            for (IBasicNetWork.PortL port:ports.get(sdhLink.getNodeTail())) {
                                if(port.getLink().getId().equals(sdhLink.getId())&&port.getStatus().equals("free")){
                                    flagTail=true;
                                    break;
                                }
                            }
                            if(h.canAdd(traffic.getBandwidthNum())&&flagHead&&flagTail){
                                links.add(sdhLink);
                            }
                        }
                    }
                }else {
                    traffic.setStatus(TrafficStatus.Fault);
                    traffic.setReason(traffic.getLayer()+"层业务无法进行规划");
                    planStatus.put(traffic.getId(),"error");
                    planReason.put(traffic.getId(),"规划失败，无相应层级链路");
                    continue;
                }


                ArrayList<IBasicNetWork.BasicLink> workRoute = new ArrayList<>();

                //分段规划
                boolean mustFlag=true;
                IBasicNetWork.BasicNode preNode=fromNode;

                List<IBasicNetWork.BasicLink> partRouteLast = algorithm.findNoMust(project,links, project.getBasicNetWork().getNodeList(), preNode, toNode);
                if(partRouteLast!=null&&!partRouteLast.isEmpty()){
                    workRoute.addAll(partRouteLast);
                }

                if(workRoute==null||workRoute.size()==0){
                    traffic.setStatus(TrafficStatus.Fault);
                    traffic.setReason("找不到工作路由");
                    planStatus.put(traffic.getId(),"error");
                    planReason.put(traffic.getId(),"规划失败，找不到工作路由");
                    continue;
                }
                if(isHopLimit&&hopLimit!=null&&workRoute!=null&&workRoute.size()>hopLimit){
                    traffic.setStatus(TrafficStatus.Fault);
                    traffic.setReason("该业务的工作路由超出跳数限制");
                    planStatus.put(traffic.getId(),"error");
                    planReason.put(traffic.getId(),"规划失败，请调高跳数限制");
                    continue;
               // List<BasicLink> linkSateWave=links;

            }

                //若为负载均衡算法
                if (strategy.equals("balance")) {
                    //links加入balanceUsedLinks1再算一次
                    if ((!mustFlag || workRoute == null || workRoute.isEmpty()) && balanceUsedLinks1.size() != 0) {
                        workRoute.clear();
                        links.addAll(balanceUsedLinks1);

                        mustFlag = true;
                        List<IBasicNetWork.BasicLink> partLinks2 = new ArrayList<>();//partLinks目的是收集links的一部分
                        IBasicNetWork.BasicNode preNode2 = fromNode;

                        partLinks2.clear();
                        partLinks2 = links;

                        List<IBasicNetWork.BasicLink> partRouteLast2 = algorithm.findNoMust(project,partLinks2, nodes, preNode2, toNode);
                        if (partRouteLast2 != null && !partRouteLast2.isEmpty()) {
                            workRoute.addAll(partRouteLast2);
                        }
                        if (isHopLimit && hopLimit != null && workRoute != null && workRoute.size() > hopLimit) {
                            traffic.setStatus(TrafficStatus.Fault);
                            traffic.setReason("该业务的工作路由超出跳数限制");
                            planStatus.put(traffic.getId(), "error");
                            planReason.put(traffic.getId(), "规划失败,请调高跳数限制");
                            continue;
                        }
                    }
                    //若还没找到，links加入balanceUsedLinks1再加入balanceUsedLinks2再算一次
                    if ((!mustFlag || workRoute == null || workRoute.isEmpty()) && balanceUsedLinks2.size() != 0) {
                        workRoute.clear();
                        links.addAll(balanceUsedLinks2);

                        mustFlag = true;
                        IBasicNetWork.BasicNode preNode2 = fromNode;
                        List<IBasicNetWork.BasicLink> partLinks3 = new ArrayList<>();//partLinks目的是收集links的一部分

                        partLinks3.clear();
                        partLinks3 = links;

                        List<IBasicNetWork.BasicLink> partRouteLast2 = algorithm.findNoMust(project,partLinks3, nodes, preNode2, toNode);
                        if (partRouteLast2 != null && !partRouteLast2.isEmpty()) {
                            workRoute.addAll(partRouteLast2);
                        }
                        if (isHopLimit && hopLimit != null && workRoute != null && workRoute.size() > hopLimit) {
                            traffic.setStatus(TrafficStatus.Fault);
                            traffic.setReason("该业务的工作路由超出跳数限制");
                            planStatus.put(traffic.getId(), "error");
                            planReason.put(traffic.getId(), "规划失败,请调高跳数限制");
                            continue;
                        }
                    }
                }



                //在计算保护路由时，应排除工作路由相关的底层fiberLink(即风险链路组)  保护路由必须和工作路由不同，
                HashSet<String> riskLinks = new HashSet<>();
                //在风险链路中添加工作路由，保证工作路由和保护路由不相同
                for (IBasicNetWork.BasicLink basicLink : workRoute) {
                    for (String s : basicLink.getFiberLinkIdSet()) {
                        riskLinks.add(s);
                    }
                }

                //如果不是无保护等级和1+恢复等级的话
                if(!traffic.getProtect().equals(ProtectString.NORMAL)&&!traffic.getProtect().equals(ProtectString.RESTORATION)){
                   IBasicNetWork.BasicLink sourceLink = workRoute.get(0);
                    IBasicNetWork.BasicLink targetLink = workRoute.get(workRoute.size() - 1);
                    List<IBasicNetWork.BasicLink> midLinks = new ArrayList<>();

                    for (int i = 1; i < workRoute.size() - 1; i++) {
                        midLinks.add(workRoute.get(i));
                    }
                    // remove route link and relevant link
                    for (Iterator<IBasicNetWork.BasicLink> it = links.iterator(); it.hasNext(); ) {
                        IBasicNetWork.BasicLink link = it.next();
                        if (link.equals(sourceLink) || link.equals(targetLink)) {
                            it.remove();
                        }
                        //似乎这里的筛除，也算是排除了风险链路组
                        else if (TopoRelevanceUtils.check(midLinks, link)) {
                            it.remove();
                        }
                    }
                    // remove passing nodes
                    Iterator<IBasicNetWork.BasicNode> itNode = nodes.iterator();
                    while (itNode.hasNext()) {
                        IBasicNetWork.BasicNode node = itNode.next();
                        if (TopoRelevanceUtils.check(midLinks, node)) {
                            itNode.remove();
                        }
                    }
                    //风险链路组，只要工作路由涉及到的fiberLink都不能用
                    Iterator<IBasicNetWork.BasicLink> it = links.iterator();
                    while (it.hasNext()) {
                        IBasicNetWork.BasicLink next = it.next();
                        Set<String> set = new HashSet<>(next.getFiberLinkIdSet());
                        for (String linkFiberId : set) {
                            for (String riskFiberId : riskLinks) {
                                if (linkFiberId.equals(riskFiberId)) {
                                    it.remove();
                                    break;
                                }
                            }
                            break;
                        }
                    }
             //至此，拓扑中的links和nodes已全部排除风险链路和节点以及工作路由和节点，接下来计算保护路由
                    List<IBasicNetWork.BasicLink> protectRoute = new ArrayList();
                    //分段规划
                    preNode = fromNode;
                    boolean partFlag = true;

                    if(!partFlag)   continue;//若在有必经节点时某段找不到，则转下个业务
                    partRouteLast = algorithm.findNoMust(project,links, nodes, preNode, toNode);
                    if(partRouteLast!=null && !partRouteLast.isEmpty()) {
                        protectRoute.addAll(partRouteLast);
                    }
                    if (protectRoute == null || protectRoute.isEmpty()) {
                        traffic.setStatus(TrafficStatus.Fault);
                        traffic.setReason("该业务无法找到保护路由，请降低业务保护等级");
                        planStatus.put(traffic.getId(), "error");
                        planReason.put(traffic.getId(), "规划失败,无法找到保护路由,请降低保护等级");
                        continue;
                    }
                    //
                    //保护路由节点数和保护跳数的比较
                    if (protectRoute.size() > traffic.getProtectLimit()) {
                        traffic.setStatus(TrafficStatus.Fault);
                        traffic.setReason("该业务无法找到满足保护跳数的保护路由");
                        planStatus.put(traffic.getId(), "error");
                        planReason.put(traffic.getId(), "规划失败,无法找到满足保护跳数的保护路由");
                        continue;
                    }
                    Route route = generateRoute(traffic, protectRoute, fromNode, toNode,ports);
                    traffic.setProtectRoute(route);
                    Node fromNode1 = basicNodetoNode(fromNode);
                    Node toNode1 = basicNodetoNode(toNode);
                    ProjectResultCenter.RouteType protectRouteType = generateRouteType(traffic, protectRoute, fromNode1, toNode1);
                   protectRouteMsg.put(traffic.getId(), protectRouteType);
                }

                Route route = generateRoute(traffic, workRoute, fromNode, toNode,ports);
                Node fromNode1 = basicNodetoNode(fromNode);
                Node toNode1 = basicNodetoNode(toNode);
                traffic.setWorkRoute(route);
                ProjectResultCenter.RouteType workRouteType = generateRouteType(traffic, workRoute,fromNode1, toNode1);
                workRouteMsg.put(traffic.getId(), workRouteType);
                traffic.setStatus(TrafficStatus.WORK);
                traffic.setReason("规划成功");
                count++;
                planStatus.put(traffic.getId(), "success");
                planReason.put(traffic.getId(), "规划成功,找到承载路由");

            }
            project.setPlanned(true);
            //针对规划失败的项目的处理
            for (DemandReportService service : project.getDemandList()) {
                if (planStatus.containsKey(service.getId())) {
                    if (planStatus.get(service.getId()).equals("error")) {
                        workRouteMsg.remove(service.getId());
                        protectRouteMsg.remove(service.getId());
                    }
                } else {
                    planStatus.put(service.getId(), "error");
                    planReason.put(service.getId(), "规划失败");

                }
            }

            //获取规划后的返回数据git@gitee.com:TjjI/test-project.git
            ProjectResultCenter.PlanResultData resultData = new ProjectResultCenter.PlanResultData(projectId,
                    workRouteMsg, protectRouteMsg, linkMsg, planStatus, planReason,ports);



            //下面是规划过程中计算和存储其他系统需要用到的值
            //计算wdm层端口利用率
            int allWavelength = 0;
            if (project.getBasicNetWork().getWdmLinks() != null) {
                for (IBasicNetWork.BasicLink w : project.getBasicNetWork().getWdmLinks()) {
                    IBasicNetWork.WdmLink w1 = (IBasicNetWork.WdmLink) w;
                    allWavelength = allWavelength + w1.getSize().intValue();
                }
            }
            int trafficNum = 0;
            if (project.getDemandList() != null) {
                for (DemandReportService t : project.getDemandList()) {
                    if (t.getLayer().equals("WDM")) trafficNum++;
                }
            }

            //设置业务状态为success或error
            List<DemandReportService> trafficList = project.getDemandList();
            for (DemandReportService traffic : trafficList) {
                    traffic.setStatus(planStatus.get(traffic.getId()));
                    traffic.setReason(planReason.get(traffic.getId()));
                }

            //下载规划结果，填入工作路由信息和保护路由信息
            for (DemandReportService traffic : trafficList) {
                if(planStatus.get(traffic.getId()).equals("success")){
                    StringBuilder workRoute = new StringBuilder();
                    StringBuilder protectRoute = new StringBuilder();
                    List<ProjectResultCenter.RouteLinkType> workLinklist = workRouteMsg.get(traffic.getId()).getLinklist();//工作路由信息
                    if(workLinklist!=null){
                        for (ProjectResultCenter.RouteLinkType routeLinkType : workLinklist) {
                            workRoute.append(routeLinkType.getName());
                            workRoute.append(";");
                        }
                        traffic.setWorkRouteMsg(new String(workRoute));
                    }
                    if(!traffic.getProtect().equals(ProtectString.NORMAL)&&!traffic.getProtect().equals(ProtectString.RESTORATION)) {
                        List<ProjectResultCenter.RouteLinkType> protectLinklist = protectRouteMsg.get(traffic.getId()).getLinklist();
                        if (protectLinklist != null) {
                            for (ProjectResultCenter.RouteLinkType routeLinkType : protectLinklist) {
                                protectRoute.append(routeLinkType.getName());
                                protectRoute.append(";");
                            }
                            traffic.setProtectRouteMsg(new String(protectRoute));
                        }
                    }
                }
            }


            //固化
            String path = ProjectFactory.storePath;
            ProjectResultCenter.savePlanResultToFile(resultData,projectId);

            boolean flag = ProjectFactory.saveObjectDataToFile( project,projectId, path);
            return count;

            }

    }

    private Node basicNodetoNode(IBasicNetWork.BasicNode fromNode) {
        Node node = new Node(fromNode.getNodeId(), fromNode.getName(), fromNode.getPointX(), fromNode.getPointY());
        return node;
    }

    //求工作和保护的WeaverResult，保证了规划成功才调用此方法
    public ProjectResultCenter.RouteType generateRouteType(DemandReportService t, List<IBasicNetWork.BasicLink> routeList, Node origin,
                                                          Node destination) throws BaseException {
        List<ProjectResultCenter.RouteNodeType> nodeMsgList = new ArrayList<>();
        List<ProjectResultCenter.RouteLinkType> linkMsglist = new ArrayList<>();
        List<Node> nodes = new ArrayList<>();
        Node preNode = origin;//nodeMsgList由linkMsg拆解下来，保证了节点顺序
        nodes.add(origin);
        for (IBasicNetWork.BasicLink link : routeList) {
            if (link instanceof IBasicNetWork.HaveTraffic) {
                //给linkMsg初始化
                if (!linkMsg.containsKey(link.getId())) {
                    linkMsg.put(link.getId(), new ProjectResultCenter.LinkMsg(link.getId(), link.getName(), link.getLayer()));
                }
                IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) link;
                if (h.addTrafficWork(t.getBandwidthNum())) {
                    linkMsg.get(link.getId()).getServiceIdSet().add(t.getId());
                }
            }
            if (link.getSourceNode().getId().equals(preNode.getId())) {
                preNode = link.getTargetNode();
            } else {
                preNode = link.getSourceNode();
            }
            nodes.add(preNode);
            linkMsglist.add(new ProjectResultCenter.RouteLinkType(link.getId(), link.getName(), link.getLayer(),
                   link.getSourceNode(),link.getTargetNode()));
        }
        for (Node node : nodes) {
            nodeMsgList.add(new ProjectResultCenter.RouteNodeType(node.getId(), node.getName(),node.getLongitude(),node.getLatitude()));
        }
        return new ProjectResultCenter.RouteType(nodeMsgList, linkMsglist);
    }

    public static Route generateRoute(DemandReportService t, List<IBasicNetWork.BasicLink> routeList, IBasicNetWork.BasicNode origin,
                                      IBasicNetWork.BasicNode destination, Map<String,List<IBasicNetWork.PortL>> portsMap) throws BaseException {
        Route route = new Route();
        // route passing node must be ordered from sourceNode to targetNode
        Set<String> nodeList = new LinkedHashSet<>();
        List<String> nodeNameList=new ArrayList<>();
        List<String> linkList = new ArrayList<>();
        List<String> linkNameList = new ArrayList<>();
        List<String> linkTypeList = new ArrayList<>();
        List<Route.RouteLinkMsg> routeLinkMsgs = new ArrayList<>();
        for (IBasicNetWork.BasicLink link : routeList) {
            Integer waveLengthNum = null;
            if (link instanceof IBasicNetWork.HaveTraffic) {
                //占用波道和带宽
                if (link instanceof IBasicNetWork.WdmLink) {
                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) link;
                    waveLengthNum = h.addWDMTrafficWork(t.getBandwidthNum());
                } else {
                    IBasicNetWork.HaveTraffic h = (IBasicNetWork.HaveTraffic) link;
                   h.addTrafficWork(t.getBandwidthNum());
                }
                //业务路由占用线路端口,路由链路头节点端口占用
                 for(IBasicNetWork.PortL port:portsMap.get(link.getNodeHead())){
                     if(port.getLink().getId().equals(link.getId())){//找到头节点对应的端口集合中与本链路相连的端口
                         if(port.getStatus().equals("free") && port.getType().equals("LinkPort")){
                             port.setStatus(t.getName());//将端口状态改为承载业务的名字
                             break; //只占用一个就跳出
                         }
                     }
                 }
                 //路由链路尾节点端口占用
                for(IBasicNetWork.PortL port:portsMap.get(link.getNodeTail())){
                    if(port.getLink().getId().equals(link.getId())){//找到头节点对应的端口集合重与本链路相连的端口
                        if(port.getStatus().equals("free") && port.getType().equals("LinkPort")){
                            port.setStatus(t.getName());//将端口状态改为承载业务的名字
                            break; //只占用一个就跳出
                        }
                    }
                }
            }
            nodeList.add(link.getSourceNode().getId());
            nodeNameList.add(link.getSourceNode().getName());
            nodeList.add(link.getTargetNode().getId());
            nodeNameList.add(link.getTargetNode().getName());
            linkList.add(link.getId());
            linkNameList.add(link.getName());
            linkTypeList.add(link.getLayer());
            Route.RouteLinkMsg routeLinkMsg = new Route.RouteLinkMsg();
            routeLinkMsg.setLinkId(link.getId());
            routeLinkMsg.setLinkName(link.getName());
            routeLinkMsg.setLinkType(link.getLayer());
            routeLinkMsg.setWaveLengthNum(waveLengthNum);
            routeLinkMsgs.add(routeLinkMsg);
        }
        // remove sourceNode and targetNode, passing nodes will be ordered without origin and destination
        nodeList.remove(origin.getNodeId());
        nodeNameList.remove(origin.getName());
        nodeList.remove(destination.getNodeId());
        nodeNameList.remove(destination.getName());
        //创建两个，占用一个线路口，保证之路端口抗毁阶段总是有支路口可用
        portsMap.get(origin.getNodeId()).add(new IBasicNetWork.PortL("branchPort","free",null));
        portsMap.get(origin.getNodeId()).add(new IBasicNetWork.PortL("branchPort",t.getName(),null));
        // set route
        route.setFromNode(origin.getNodeId());
        route.setToNode(destination.getNodeId());
        route.setNodeList(nodeList);
        route.setNodeNameList(nodeNameList);
        route.setLinkList(linkList);
        route.setLinkNameList(linkNameList);
        route.setLinkTypeList(linkTypeList);
        route.setRouteLinkMsgs(routeLinkMsgs);
        route.setHop(routeLinkMsgs.size());
        route.setSuccess(true);
        return route;
    }




    @Override
    public Object planRes(String projectId) throws BaseException {
        if (null == projectId) {
            throw new BaseException("projectId为空");
        }
        Project project = ProjectFactory.getObjectFromFile(projectId, ProjectFactory.storePath);
        if (project == null) {
            throw new BaseException(projectId + "无效");
        }
        List<DemandReportService> trafficList = project.getDemandList();
        return trafficList;
    }

    //判断承载了几个同源同溯的业务，默认是0
    private int judgeTYTS(Map<String, ProjectResultCenter.LinkMsg> linkMsg, String linkId, List<DemandReportService> trafficList, String nodeHeadName, String nodeTailName) {
        int num = 0;
        if (linkMsg != null && linkMsg.get(linkId) != null && linkMsg.get(linkId).getServiceIdSet() != null) {
            for (String serviceId : linkMsg.get(linkId).getServiceIdSet()) {
                for (DemandReportService t : trafficList) {
                    if (t.getId().equals(serviceId)) {
                        if (t.getNodeHeadName().equals(nodeHeadName) && t.getNodeTailName().equals(nodeTailName)) {
                            num++;
                        }
                    }
                }
            }
        }
        return num;
    }
    //释放链路资源，清空已分配的工作路由和保护路由

    private void clear(Project project) {
        if(project.getBasicNetWork().getWdmLinks().size()!=0){
            for (IBasicNetWork.BasicLink wdmLink : project.getBasicNetWork().getWdmLinks()) {
                ((IBasicNetWork.WdmLink)wdmLink).releaseZLD();
            }
        }
        if(project.getBasicNetWork().getOtnLinks().size()!=0){
            for (IBasicNetWork.BasicLink otnLink : project.getBasicNetWork().getOtnLinks()) {
                ((IBasicNetWork.OtnLink)otnLink).releaseZLD();;
            }
        }
        if(project.getBasicNetWork().getOtnLinks().size()!=0){
            for (IBasicNetWork.BasicLink sdhLink : project.getBasicNetWork().getSdhLinks()) {
                ((IBasicNetWork.SdhLink)sdhLink).releaseZLD();
            }
        }

        for (DemandReportService traffic : project.getDemandList()) {
            traffic.setWorkRoute(new Route());
            traffic.setProtectRoute(new Route());
            traffic.setReason("");
            traffic.setStatus(TrafficStatus.FREE);
        }
        //清空端口占用
        for (Map.Entry<String,List<IBasicNetWork.PortL>> entry:
                project.getBasicNetWork().getPorts().entrySet()) {
            for (IBasicNetWork.PortL port:entry.getValue()) {
                port.setStatus("free");
            }
        }
    }


}
